"""
债券买入持有策略回测示例
"""
import os,sys
project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(project_root)

from datetime import datetime, timedelta
import pandas as pd
import numpy as np

from engine.engine import BacktestEngine
from engine.assets import Bond, Repo
from engine.event import AssetType, CashFlowType
from strategy.examples.bond_buy_hold import BondBuyHoldStrategy
from engine.assets import Bond, Repo, AssetType, CashFlowType
from visualization.performance import PerformanceAnalyzer, PerformanceVisualizer

def generate_test_data(start_date: datetime, end_date: datetime) -> pd.DataFrame:
    """生成测试数据"""
    # 生成日期范围
    dates = pd.date_range(start=start_date, end=end_date, freq='D')
    
    # 生成债券价格数据
    np.random.seed(42)
    n_days = len(dates)
    
    # 债券价格始终保持在100
    prices = np.full(n_days, 100.0)
    
    # 生成到期收益率数据（假设在3%附近波动）
    ytm = np.random.normal(0.03, 0.002, n_days)
    
    # 生成回购利率数据（假设在2%附近波动）
    # repo_rate = np.random.normal(0.02, 0.001, n_days)
    repo_rate = np.full(n_days, 0.02) 
    # 创建市场数据DataFrame
    market_data = pd.DataFrame({
        'bond_1_close': prices,
        'bond_1_ytm': ytm,
        'repo_1_close': repo_rate,
        'bond_1_volume': 10000,  # 成交量
        'repo_1_volume': 100000  # 成交量
    }, index=dates)
    return market_data
def main():
    """主函数"""
    print("开始回测...")
    
    # 设置回测参数
    start_date = datetime(2024, 1, 1)
    end_date = datetime(2025, 1, 1)
    initial_cash = 1000000.0  # 初始资金100万
    leverage = 1  # 使用2倍杠杆
    
    # 生成测试数据
    market_data = generate_test_data(start_date, end_date)
    
    # 创建债券和回购
    # 计算付息日期和现金流
    days_between_payments = 366 // 2  # 半年付息一次
    first_payment_date = start_date + timedelta(days=days_between_payments)
    second_payment_date = first_payment_date + timedelta(days=days_between_payments)
    
    # 创建明确的现金流列表
    bond_cashflows = [
        (first_payment_date, 1.83, CashFlowType.INTEREST),   # 第一次付息 3%/2 = 1.5%
        (second_payment_date, 1.83, CashFlowType.INTEREST),  # 第二次付息 3%/2 = 1.5%
        (end_date, 100.0, CashFlowType.PRINCIPAL)  # 到期还本
    ]
    
    bond = Bond(
        symbol='bond_1',
        asset_type=AssetType.BOND,
        par_value=100.0,  # 面值
        value_date=start_date,
        maturity_date=end_date,
        # payment_frequency=2,
        # coupon_rate=0.0365,
        explicit_cashflows=bond_cashflows
    )

    # 创建回购
    repo1 = Repo(
        symbol='repo_1',
        asset_type=AssetType.REPO,
        principal=1,
        repo_rate=0.03,  # 回购利率2%
        start_date=start_date,
        end_date=start_date + timedelta(days=170)  # 半年回购
    )
    repo2 = Repo(
        symbol='repo_2',
        asset_type=AssetType.REPO,
        principal=1,
        repo_rate=0.03,  # 回购利率2%
        start_date=start_date + timedelta(days=170),
        end_date=start_date + timedelta(days=364)  # 半年回购
    )
    
    
    
    # 创建回测引擎
    engine = BacktestEngine(
        initial_capital=initial_cash,
        commission_rate=0.000,
        slippage_rate=0.000
    )
    # 创建策略
    strategy = BondBuyHoldStrategy(name="债券买入持有策略", leverage=leverage)

    # 添加资产和数据
    engine.add_asset(bond)
    engine.add_asset(repo1)
    engine.add_asset(repo2)
    
    # 将市场数据分别添加到对应的资产
    bond_data = market_data[[ 'bond_1_close', 'bond_1_ytm', 'bond_1_volume']].copy()
    bond_data.columns = [ 'close', 'ytm', 'volume']
    engine.add_market_data('bond_1', bond_data)
    
    repo_data = market_data[['repo_1_close', 'repo_1_volume']].copy()
    repo_data.columns = [ 'close', 'volume']
    engine.add_market_data('repo_1', repo_data)
    engine.add_market_data('repo_2', repo_data)
    
    # 设置策略
    engine.set_strategy(strategy)
    
    # 运行回测
    print("开始运行回测...")
    results = engine.run_backtest()
    print(results) #打印持仓
    results.to_csv("example3.csv")
    
    # 计算性能指标
    metrics = engine.get_performance_metrics()
    print("回测完成!")
    print("指标:", metrics)
    
    # 分析和可视化结果
    analyzer = PerformanceAnalyzer(results)
    visualizer = PerformanceVisualizer(analyzer,trades=engine.trades)
    visualizer.export_html_report("example3.html")
    
    return results, metrics


if __name__ == "__main__":

    def timeit(func):
        import time
        start_time = time.time()
        func()
        end_time = time.time()
        print(f"Time taken: {end_time - start_time} seconds")
    timeit(main)
